/*
 * Galaxium Messenger
 * Copyright (C) 2008 Paul Burton <paulburton89@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.IO;
using System.Text;
using System.Xml.Serialization;

using NUnit.Framework;

using Galaxium.Protocol.Msn;
using Galaxium.Protocol.Msn.Soap;
using Galaxium.Protocol.Msn.Soap.BodyParts;
using Galaxium.Protocol.Msn.Soap.Headers;

[TestFixture]
public class SOAPSerialization
{
	[Test]
	public void MemberTest ()
	{
		Member m = new EmailMember ();
		
		m.MembershipId = 1000;
		m.Type = MemberType.Email;
		m.LastChanged = DateTime.MaxValue;
		m.Deleted = true;
		m.AddAnnotation ("Test", "Test Value1");
		m.AddAnnotation ("Test 2", "TestValue2");
		
		Member n = SerializeThenDeserialize (m, 2) as Member;
		
		Assert.IsNotNull (n, "member is null");
		Assert.AreEqual (m.MembershipId, n.MembershipId, "MembershipID does not match");
		Assert.AreEqual (m.Type, n.Type, "Type does not match");
		Assert.AreEqual (m.LastChanged, n.LastChanged, "LastChanged does not match");
		Assert.AreEqual (m.LastChangedSpecified, n.LastChangedSpecified, "LastChangedSpecified does not match");
		Assert.AreEqual (m.Deleted, n.Deleted, "Deleted does not match");
		Assert.AreEqual (m.DeletedSpecified, n.DeletedSpecified, "DeletedSpecified does not match");
		Assert.AreEqual (m.Annotations.Count, n.Annotations.Count, "Annotations.Count does not match");
		Assert.AreEqual (m.AnnotationsSpecified, n.AnnotationsSpecified, "AnnotationsSpecified does not match");
		Assert.AreEqual ("Test Value1", n.Annotations["Test"], "Annotation 'Test' does not match");
		Assert.AreEqual ("TestValue2", n.Annotations["Test 2"], "Annotation 'Test 2' does not match");
	}
	
	[Test]
	public void ABContactTest ()
	{
		ABContact c = new ABContact ();
		
		Assert.AreEqual (null, c.Info, "Info non-null default");
		
		c.Deleted = true;
		c.Id = new Guid ();
		c.LastChange = DateTime.MaxValue;
		c.PropertiesChanged = "Name";
		
		Assert.AreEqual (true, c.DeletedSpecified, "DeletedSpecified is false");
		Assert.AreEqual (true, c.IdSpecified, "IdSpecified is false");
		Assert.AreEqual (false, c.InfoSpecified, "InfoSpecified is true");
		Assert.AreEqual (true, c.LastChangeSpecified, "LastChangeSpecified is false");
		Assert.AreEqual (true, c.PropertiesChangedSpecified, "PropertiesChangedSpecified is false");
		
		ABContact d = SerializeThenDeserialize (c, 2) as ABContact;
		
		Assert.AreEqual (c.Deleted, d.Deleted, "Deleted does not match");
		Assert.AreEqual (c.DeletedSpecified, d.DeletedSpecified, "DeletedSpecified does not match");
		Assert.AreEqual (c.Id, d.Id, "Id does not match");
		Assert.AreEqual (c.IdSpecified, d.IdSpecified, "IdSpecified does not match");
		Assert.AreEqual (c.Info, d.Info, "Info does not match");
		Assert.AreEqual (c.InfoSpecified, d.InfoSpecified, "InfoSpecified does not match");
		Assert.AreEqual (c.LastChange, d.LastChange, "LastChange does not match");
		Assert.AreEqual (c.LastChangeSpecified, d.LastChangeSpecified, "LastChangeSpecified does not match");
		Assert.AreEqual (c.PropertiesChanged, d.PropertiesChanged, "PropertiesChanges does not match");
		Assert.AreEqual (c.PropertiesChangedSpecified, d.PropertiesChangedSpecified, "PropertiesChangedSpecified does not match");
		
		c.Info = new ContactInfo ();
		
		Assert.AreEqual (true, c.InfoSpecified, "InfoSpecified is false");
		Assert.AreEqual (null, c.Info.Annotations, "Non-null Annotations default");
		Assert.AreEqual (null, c.Info.Emails, "Non-null Emails default");
		Assert.AreEqual (null, c.Info.GroupIds, "Non-null GroupIds default");
		Assert.AreEqual (null, c.Info.MemberInfo, "Non-null MemberInfo default");
		
		c.Info.Birthdate = DateTime.MaxValue;
		c.Info.CID = 10000;
		c.Info.DisplayName = "Mr A";
		c.Info.FirstName = "A";
		c.Info.Gender = ContactGender.Male;
		c.Info.HasSpace = true;
		c.Info.IsMessengerUser = true;
		c.Info.IsPassportNameHidden = false;
		c.Info.IsSmtp = false;
		c.Info.LastName = "A";
		c.Info.PassportName = "a@a.com";
		c.Info.Type = ContactType.Messenger;
		
		ABContact e = SerializeThenDeserialize (c, 2) as ABContact;
		
		Assert.IsNotNull (e.Info, "Info is null");
		
		Assert.AreEqual (true, e.Info.BirthdateSpecified);
		Assert.AreEqual (true, e.Info.CIDSpecified);
		Assert.AreEqual (true, e.Info.DisplayNameSpecified);
		Assert.AreEqual (true, e.Info.FirstNameSpecified);
		Assert.AreEqual (true, e.Info.GenderSpecified);
		Assert.AreEqual (true, e.Info.HasSpaceSpecified);
		Assert.AreEqual (true, e.Info.IsMessengerUserSpecified);
		Assert.AreEqual (true, e.Info.IsPassportNameHiddenSpecified);
		Assert.AreEqual (true, e.Info.IsSmtpSpecified);
		Assert.AreEqual (true, e.Info.LastNameSpecified);
		Assert.AreEqual (true, e.Info.PassportNameSpecified);
		Assert.AreEqual (true, e.Info.TypeSpecified);
		
		Assert.AreEqual (DateTime.MaxValue, e.Info.Birthdate, "Info.Birthdate does not match");
		Assert.AreEqual (10000, e.Info.CID, "Info.CID does not match");
		Assert.AreEqual ("Mr A", e.Info.DisplayName, "Info.DisplayName does not match");
		Assert.AreEqual ("A", e.Info.FirstName, "Info.FirstName does not match");
		Assert.AreEqual (ContactGender.Male, e.Info.Gender, "Info.Gender does not match");
		Assert.AreEqual (true, e.Info.HasSpace, "Info.HasSpace does not match");
		Assert.AreEqual (true, e.Info.IsMessengerUser, "Info.IsMessengerUser does not match");
		Assert.AreEqual (false, e.Info.IsPassportNameHidden, "Info.IsPassportNameHidden does not match");
		Assert.AreEqual (false, e.Info.IsSmtp, "Info.IsSmtp does not match");
		Assert.AreEqual ("A", e.Info.LastName, "Info.Lastname does not match");
		Assert.AreEqual ("a@a.com", e.Info.PassportName, "Info.PassportName does not match");
		Assert.AreEqual (ContactType.Messenger, e.Info.Type, "Info.Type does not match");
	}
	
	[Test]
	public void MembershipTest ()
	{
		Membership m = new Membership ();
		
		Assert.AreEqual (null, m.Members, "Non-null Members default");
		
		m.MemberRole = MemberRole.Block;
		m.Members = new MemberCollection ();
		m.Members.Add (new PassportMember ());
		
		Assert.AreEqual (true, m.MemberRoleSpecified, "MemberRoleSpecified is false");
		Assert.AreEqual (true, m.MembersSpecified, "MembersSpecified is false");
		
		Membership n = SerializeThenDeserialize (m, 2) as Membership;
		
		Assert.IsNotNull (n.Members, "Members is null");
		
		Assert.AreEqual (m.MemberRole, n.MemberRole, "MemberRole does not match");
		Assert.AreEqual (m.MemberRoleSpecified, n.MemberRoleSpecified, "MemberRoleSpecified does not match");
		Assert.AreEqual (m.Members.Count, n.Members.Count, "Members.Count does not match");
		Assert.AreEqual (m.MembersSpecified, n.MembersSpecified, "MembersSpecified does not match");
	}
	
	object SerializeThenDeserialize (object obj, int times)
	{
		object o = obj;
		
		for (int i = 0; i < times; i++)
		{
			o = Deserialize (Serialize (o), o.GetType ());
			
			if (o == null)
				return null;
		}
		
		return o;
	}
	
	string Serialize (object obj)
	{
		XmlSerializer s = new XmlSerializer (obj.GetType ());
		StringBuilder sb = new StringBuilder ();
		StringWriter str = new StringWriter (sb);
		
		s.Serialize (str, obj);
		
		str.Close ();
		return sb.ToString ();
	}
	
	object Deserialize (string str, Type type)
	{
		XmlSerializer s = new XmlSerializer (type);
		StringReader sr = new StringReader (str);
		
		object obj = s.Deserialize (sr);
		
		sr.Close ();
		
		return obj;
	}
}
